﻿#region Copyright © 2008 Rickard Nilsson [rickard@rickardnilsson.net]
/*
 * This software is an altered version of the original and is provied 'as-is'.
 */
#endregion
#region Copyright © 2001-2003 Jean-Claude Manoli [jc@manoli.net]
/*
 * This software is provided 'as-is', without any express or implied warranty.
 * In no event will the author(s) be held liable for any damages arising from
 * the use of this software.
 * 
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 * 
 *   1. The origin of this software must not be misrepresented; you must not
 *      claim that you wrote the original software. If you use this software
 *      in a product, an acknowledgment in the product documentation would be
 *      appreciated but is not required.
 * 
 *   2. Altered source versions must be plainly marked as such, and must not
 *      be misrepresented as being the original software.
 * 
 *   3. This notice may not be removed or altered from any source distribution.
 */
#endregion

using System;
using System.Text.RegularExpressions;
using System.Web;
using CodeFormatter;

/// <summary>
/// Converts text to formatted syntax highlighted code.
/// </summary>
internal static class SourceFormatter
{
    /// <summary>
    /// Returns the formatted text.
    /// </summary>
    /// <param name="options">Whatever options were set in the regex groups.</param>
    /// <param name="text">Send the e.body so it can get formatted.</param>
    /// <returns>The formatted string of the match.</returns>
    internal static string Highlight(HighlightOptions options, string text)
    {
        switch (options.Language)
        {
            case "c#":
                CSharpFormat csf = new CSharpFormat();
                csf.LineNumbers = options.DisplayLineNumbers;
                csf.Alternate = options.AlternateLineNumbers;
                text = HttpContext.Current.Server.HtmlDecode(text);
                return csf.FormatCode(text);

            case "vb":
                VisualBasicFormat vbf = new VisualBasicFormat();
                vbf.LineNumbers = options.DisplayLineNumbers;
                vbf.Alternate = options.AlternateLineNumbers;
                return vbf.FormatCode(text);

            case "js":
                JavaScriptFormat jsf = new JavaScriptFormat();
                jsf.LineNumbers = options.DisplayLineNumbers;
                jsf.Alternate = options.AlternateLineNumbers;
                return HttpContext.Current.Server.HtmlDecode(jsf.FormatCode(text));

            case "html":
                HtmlFormat htmlf = new HtmlFormat();
                htmlf.LineNumbers = options.DisplayLineNumbers;
                htmlf.Alternate = options.AlternateLineNumbers;
                text = StripHtml(text).Trim();
                string code = htmlf.FormatCode(HttpContext.Current.Server.HtmlDecode(text)).Trim();
                return code.Replace(Environment.NewLine, "<br />");

            case "xml":
                HtmlFormat xmlf = new HtmlFormat();
                xmlf.LineNumbers = options.DisplayLineNumbers;
                xmlf.Alternate = options.AlternateLineNumbers;
                text = StripHtml(text).Trim();
                string xml = xmlf.FormatCode(HttpContext.Current.Server.HtmlDecode(text)).Trim();
                return xml.Replace(Environment.NewLine, "<br />");

            case "tsql":
                TsqlFormat tsqlf = new TsqlFormat();
                tsqlf.LineNumbers = options.DisplayLineNumbers;
                tsqlf.Alternate = options.AlternateLineNumbers;
                return HttpContext.Current.Server.HtmlDecode(tsqlf.FormatCode(text));

            case "msh":
                MshFormat mshf = new MshFormat();
                mshf.LineNumbers = options.DisplayLineNumbers;
                mshf.Alternate = options.AlternateLineNumbers;
                return HttpContext.Current.Server.HtmlDecode(mshf.FormatCode(text));
        }

        return string.Empty;
    }

    private static Regex _Regex = new Regex("<[^>]*>", RegexOptions.Compiled);

    private static string StripHtml(string html)
    {
        if (string.IsNullOrEmpty(html)) return string.Empty;
        return _Regex.Replace(html, string.Empty);
    }
}

/// <summary>
/// Handles all of the options for changing the rendered code.
/// </summary>
internal class HighlightOptions
{
    private string language, title, code;
    private bool displayLineNumbers = false;
    private bool alternateLineNumbers = false;

    public HighlightOptions()
    {
    }

    public HighlightOptions(string language, string title, bool linenumbers, string code, bool alternateLineNumbers)
    {
        this.language = language;
        this.title = title;
        this.alternateLineNumbers = alternateLineNumbers;
        this.code = code;
        this.displayLineNumbers = linenumbers;
    }

    public string Code
    {
        get { return code; }
        set { code = value; }
    }
    public bool DisplayLineNumbers
    {
        get { return displayLineNumbers; }
        set { displayLineNumbers = value; }
    }
    public string Language
    {
        get { return language; }
        set { language = value; }
    }
    public string Title
    {
        get { return title; }
        set { title = value; }
    }
    public bool AlternateLineNumbers
    {
        get { return alternateLineNumbers; }
        set { alternateLineNumbers = value; }
    }
}